
/******************************************************************************
 * Copyright 2022 The Airos Authors. All Rights Reserved.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *****************************************************************************/

/**
  * @file     device_factory.h
  * @brief    gnss设备工厂
  * @version  V1.0.0
  */

#pragma once

#include "device_base.h"

#include <functional>
#include <map>

namespace os {
namespace v2x {
namespace device {

/**
  * @brief  Ins设备注册工厂
  */
class InsDeviceFactory {
public:
    using CONSTRUCT = std::function<InsDevice*(const GnssCallBack& cb_1, const IMUCallBack& cb_2)>;

    template<typename Inherit>
    class Register_t {
    public:
        Register_t(const std::string& key) {
            InsDeviceFactory::Instance().map_.emplace(key, [] (const GnssCallBack& cb_1, const IMUCallBack& cb_2) 
                { 
                    return new Inherit(cb_1,cb_2);
                });
        }
    };
    /**
     * @brief      用于获取指定Ins设备实例的unique指针
     * @param[in]  key 指定Ins设备名
     * @retval     指定Ins设备实例的unique指针
     */
    std::unique_ptr<InsDevice> GetUnique(const std::string& key, const GnssCallBack& cb_1, const IMUCallBack& cb_2);
    /**
     * @brief      用于获取指定Ins设备实例的shared指针
     * @param[in]  key 指定Ins设备名
     * @retval     指定Ins设备实例的shared指针
     */
    std::shared_ptr<InsDevice> GetShared(const std::string& key, const GnssCallBack& cb_1, const IMUCallBack& cb_2);
    /**
     * @brief      用于获取Ins设备工厂实例（单例）
     * @retval     Ins设备工厂实例
     */
    static InsDeviceFactory& Instance();
    
private:
    InsDevice* Produce(const std::string& key, const GnssCallBack& cb_1, const IMUCallBack& cb_2);

    InsDeviceFactory() {};
    InsDeviceFactory(const InsDeviceFactory&) = delete;
    InsDeviceFactory(InsDeviceFactory&&) = delete;

private:
    std::map<std::string, CONSTRUCT> map_;
};

#define V2XOS_INS_REG(T) v2xos_reg_func_str_##T##_
/**
 * @brief      用于注册指定Ins设备
 * @param[in]  T 具体Ins设备子类型
 * @param[in]  key 注册的Ins设备名字
 */
#define V2XOS_INS_REG_FACTORY(T, key) static InsDeviceFactory::Register_t<T> V2XOS_INS_REG(T)(key);

}
}
}